#ifndef Net_EpollListenServer_INCLUDED
#define Net_EpollListenServer_INCLUDED

#include <set>
#include <sys/epoll.h>
#include <vector>

#include "socket.h"
#include "mutex.h"
#include "runnable.h"
#include "thread.h"
#include "event.h"
#include "epolldispatcher.h"

using std::set;
using std::vector;

class EpollEventThread;

class EventFdTimeOutThread : public Runnable
{
public:
    EventFdTimeOutThread(EpollEventThread& thread)
    :m_thread(thread),
    m_exitflag(false)
    {
    }
    
    virtual void run();

    void stop()
    {
        m_exitflag = true;
    }
private:
    EpollEventThread&       m_thread;
    bool                    m_exitflag;
    Event                   m_event;
};

class EpollEventThread: public Runnable
{
public:
    EpollEventThread(int epollfd,int poolsize,
        unsigned int dispatcher_fdtimeout,
        EpollClientFactory *pf);
    
    ~EpollEventThread();

    virtual void run();

    void closingFd(int timeoutFd);
    void getTimeoutFds(std::set<int>& timeoutFds);
    
    void addMaxEvent(int n)
    {
        ScopedMutex lock(&m_mutex);
        m_fdsize += n;
    }

    void reduceMaxEvent(int n)
    {
        ScopedMutex lock(&m_mutex);
        m_fdsize -= n;
    }

    void stop()
    {
        m_exitflag = true;
    }
private:
    int                 m_epollfd;
    int                 m_poolsize;
    //                  监听的 fd 数
    unsigned int        m_fdsize;
    bool                m_exitflag;
    EpollClientFactory  *m_factory;
    ThreadPool          *m_pool;
    EpollDispatcher     *m_dispatcher;


    set<int>            m_timeoutFds;
    Mutex               m_mutex;
    EventFdTimeOutThread*  m_timeoutTarget;
    Thread              m_timeoutThread;
    Event               m_event;
};

class EpollListenServer: public Socket
{
public:
    // epollnum： num of creating epollfd,for recving or sending,except for listening
    // dispatcher_threadpoolsize: size of threadpool used by dispatcher
    EpollListenServer(const SocketAddress& address, 
            EpollClientFactory* pf,
            unsigned int eventepollnum = 4,
            unsigned int dispatcher_threadpoolsize = 4,
            unsigned int dispatcher_fdtimeout = 0,
            bool reuseAddress = true,
            EPOLL_MODE mode = EPOLLMODE_ET,
            int backlog = LISTEN_BACKLOG);

    // epollnum： num of creating epollfd,for recving or sending,except for listening
    EpollListenServer(unsigned int port, 
            EpollClientFactory* pf,
            unsigned int eventepollnum = 4,
            unsigned int dispatcher_threadpoolsize = 4,
            unsigned int dispatcher_fdtimeout = 0,
            bool reuseAddress = true,
            EPOLL_MODE mode = EPOLLMODE_ET,
            int backlog = LISTEN_BACKLOG);
    
    virtual ~EpollListenServer();
    
    void wait();

    void stopWait()
    {
        if (!m_exitflag)
        {
            m_exitflag = true;
        }
    }
    
    int acceptConnection();
    
    /// monitor info
    bool running()
    {
        return !m_exitflag;
    }
    
    bool isEdegTrigerMode()
    {
        return m_mode == EPOLLMODE_ET;
    }

private:
    EpollListenServer& operator = (const EpollListenServer& server);
    void init(unsigned long maxopenfd = MAXOPENFD);
    
private:
    int                 m_epollFd;
    unsigned int        m_eventepollnum;
    int                 m_dispatcher_threadpoolsize;
    int                 m_dispatcher_fdtimeout;
    EPOLL_MODE          m_mode;
    
    int                 *m_eventepollfds;
    EpollClientFactory  *m_factory;
    
    vector<Thread*>     m_threads;
    vector<EpollEventThread*> m_threadtargets;
        // 根据 epollnum 建立的一组 epollfd
    bool                m_exitflag;
};

#endif



